﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer;
using Microsoft.SqlServer.Server;


public partial class DamerauLevenshtein
{
    [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, Name = "fn_damerau_levenshtein", SystemDataAccess = SystemDataAccessKind.None)]
    public static SqlInt64 EditDistance(SqlString inSrc, SqlString inTrg, SqlBoolean ignoreCase)  
	{    
		string strSrc = ignoreCase ? inSrc.Value.ToLower() : inSrc.Value;    
		string strTrg = ignoreCase ? inTrg.Value.ToLower() : inTrg.Value;    
		int lenSrc = strSrc.Length;    
		int lenTrg = strTrg.Length;    
		int[,] matrix = new int[lenSrc + 1, lenTrg + 1];
        int cost = 0;


        for (int s = 0; s <= lenSrc; s++)
        {
            matrix[s, 0] = s;
        } //for (int s = 0; s <= lenSrc; s++)   

        for (int t = 0; t <= lenTrg; t++)
        {
            matrix[0, t] = t;
        } //for (int t = 0; t <= lenTrg; t++)    


        for (int t = 1; t <= lenTrg; t++)
        {
            for (int s = 1; s <= lenSrc; s++)
            {
                cost = (strSrc.Substring(s - 1) == strTrg.Substring(t - 1) ? 0 : 1);

                if (strSrc[s - 1] == strTrg[t - 1])
                    matrix[s, t] = matrix[s - 1, t - 1];
                else
                    matrix[s, t] = Math.Min(Math.Min(matrix[s - 1, t] + 1      // deletion            
                                                    , matrix[s, t - 1] + 1)    // insertion            
                                           , matrix[s - 1, t - 1] + cost);     // substitution      

                if (s > 0 && t > 0 && strSrc[s] == strTrg[t - 1] && strSrc[s - 1] == strTrg[t])
                    {
                        matrix[s, t] = Math.Min(matrix[s, t], matrix[s - 2, t - 2] + cost);       // transposition
                    }
            }//for (int s = 1; s <= lenSrc; s++)    
        } //for (int t = 1; t <= lenTrg; t++)               

        return new SqlInt64(matrix[lenSrc, lenTrg]);  
	}
};

